
module jade.tpl.js.JArray ;

import jade.tpl.Template ;

final class JAA(K, V) : Dobject {
	static assert( isSomeString!(K)  || std.traits.isNumeric!(K) ) ;
	alias V[K]	Base ;
	Base	 	_obj ;
	static if( isPointer!(V) && is( pointerTarget!(V)==struct) ) {
		alias V				pThis ;
		alias pointerTarget!(V)	This ;
	} else static if( is(V==struct) ){
		alias V	This ;
		alias V	pThis ;
	}else static if( is(V==class) ){
		alias V	This ;
		alias V	pThis ;
	} else static if(  isSomeString!(V)  || std.traits.isNumeric!(V) ) {
		
	} else {
		static assert(false);
	}
	alias JAA!(K, V) JAA_Object ;
	static Dobject 	jaa_prototype ;
	static Dobject 	jaa_foreach ;
	
	final this(Dobject prototype) {
		assert(prototype is Dobject_prototype);
		super(prototype);
	}
	
	final this(Base obj ) {
		if( jaa_prototype is null ) {
			jaa_prototype	= new Dobject(Dobject_prototype);
			jaa_prototype.Put(TEXT_forEach,
					new DnativeFunction(&JAA_forEach, TEXT_forEach, 0 , Dfunction.getPrototype) ,
					DontEnum | DontDelete | ReadOnly
				);
		}
		super(jaa_prototype) ;
		_obj	= obj ;
	}
	
	static void* JAA_forEach(Dobject pthis, CallContext* cc, Dobject othis, Value* ret, Value[] args) {
		ErrInfo errinfo;
		JAA_Object _this	= cast(JAA_Object) othis ;
		if( _this is null ) {
                	return RuntimeError(&errinfo, ERR_TYPE_ERROR , TEXT_forEach);
		}
		assert(_this._obj !is null);
		if( args.length > 0 && args[0].isObject ){
			auto fn	= cast(Dfunction) args[0].toObject ;
			Dobject call_this = othis ;
			if( args.length > 1 && args[1].isObject ){
				call_this	= args[1].toObject ;
			}
			if( fn !is null) {
				static if(  isSomeString!(V)  || std.traits.isNumeric!(V) ) {
					foreach(K key,  V val; _this._obj ) {
						scope Value 	_ret;
						scope Value[2]	_args ;
						
						static if( isSomeString!(V) ) {
							_args[0].putVstring( val) ;
						} else static if( std.traits.isNumeric!(K) ) {
							_args[0].putVnumber( val) ;
						}
						static if( isSomeString!(K) ) {
							_args[1].putVstring(key) ;
						} else static if( std.traits.isNumeric!(K) ) {
							_args[1].putVnumber(key) ;
						}
						Value* __ret ;
						__ret = cast(Value*) fn.Call( Tpl_Factory.program.callcontext, call_this, &_ret, _args );
						if( __ret !is null ){
							Log( __ret.toString );
							assert(false);
						}
					}
					
				} else {
					assert(false);
				}
			}
		}
		ret.putVobject(othis);
		return null ;
	}
	
	final Value* Get(d_string _name , uint hash) {
		Value* ret ;
		ret	= proptable.get(_name, hash) ;
		if( ret !is null ){
			return ret ;
		}
		static if(  isSomeString!(K) ) {
			V* id_ptr     = _name in _obj ;
		} else {
			V* id_ptr     = to!K(_name) in _obj ;
		}
		if( id_ptr is null ) {
			return super.Get(_name, hash) ;
		}
		ret	= new Value ;
		static if( isSomeString!(V) || std.traits.isNumeric!(V) ) {
			V _val	= *id_ptr ;
			static if( isSomeString!(V)  ){
				ret.putVstring(*id_ptr ) ;
			} else {
				v.putVnumber(*id_ptr);
			}
			proptable.put(_name, ret, DontDelete | ReadOnly );
		} else static if( is(V==class)  ) {
			alias JType!(This) _JType ;
			auto _dval	= new _JType(*id_ptr) ;
			proptable.put(_name, _dval, DontDelete | ReadOnly );
			ret.putVobject(_dval) ;
		} else static if( is(V==struct) ){
			alias JType!(This) _JType ;
			auto _dval	= new _JType(id_ptr) ;
			proptable.put(_name, _dval, DontDelete | ReadOnly );
			ret.putVobject(_dval) ;
		}  else static if( isPointer!(T) && is( pointerTarget!(T)==struct) ) {
			alias JType!(This) _JType ;
			auto _dval	= new _JType(*id_ptr) ;
			proptable.put(_name, _dval, DontDelete | ReadOnly );
			ret.putVobject(_dval) ;
		} else {
			static assert(false);
		}
		return  ret ;
	}
}